package cn.edu.hstc.wm.exception;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Date;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Environment;
import android.os.Looper;
import cn.edu.hstc.wm.AppApplication;
import cn.edu.hstc.wm.utils.FileUtils;
import cn.edu.hstc.wm.utils.Utility;

/**
 * @ClassName: DefaultExceptionHandler
 * @Description: 默认的异常处理 , 当 Thread 因未捕获的异常而突然终止时，调用处理程序。
 * 
 * @ModificationHistory
 */
public class AppException extends Exception implements UncaughtExceptionHandler {

	/** */
	private static final long serialVersionUID = 8616304282810907591L;
	private static AppException sCrashHandler = null;
	private AppApplication mApp;
	private final String LOG_NAME = "crash.log";
	private final String SAVE_PATH = "app_log";

	/** 获取CrashHandler实例 */
	public static AppException getInstance() {
		if (sCrashHandler == null)
			sCrashHandler = new AppException();
		return sCrashHandler;
	}

	public void init(AppApplication app) {
		mApp = app;
		// 设置该类为线程默认UncatchException的处理器。
		Thread.setDefaultUncaughtExceptionHandler(this);
	}

	/**
	 * 当UncaughtException发生时会回调该函数来处理
	 */
	@Override
	public void uncaughtException(Thread thread, final Throwable ex) {
		System.out.println("system wrong....");

		// 应用程序信息收集
		collectCrashApplicationInfo(mApp);

		// 异常信息收集
		collectCrashExceptionInfo(thread, ex);

		// 判断是否为UI线程异常，thread.getId()==1 为UI线程

		// 不是UI线程
		if (thread.getId() != 1) {
			thread.interrupt();
			new Thread() {
				public void run() {
					Looper.prepare();
					showTipDialog(ex);
					Looper.loop();
				}
			}.start();
		}
		// 是UI线程
		else {
			showTipDialog(ex);
		}
	}

	/**
	 * 保存Crash信息到日志文件中
	 * 
	 * @param ex
	 */
	private void saveCrashInfoToFile(String str) {
		PrintStream printStream = null;
		try {
			// 保存到日志文件中
			File file = FileUtils.createFile(Environment.getExternalStorageDirectory() + File.separator + SAVE_PATH + File.separator, LOG_NAME);
			printStream = new PrintStream(file);
			printStream.println(str);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (printStream != null) {
				printStream.close();
			}
		}
	}

	/**
	 * 收集设备信息
	 * 
	 * @param mApp2
	 */
	@SuppressWarnings("deprecation")
	private void collectCrashApplicationInfo(AppApplication app) {
		// TODO 收集屏幕信息,sdk版本,设备rom ram
		StringBuffer info = new StringBuffer();
		info.append("============ 系统信息  ============\n");
		info.append("包名 : " + app.getPackageName() + "\n");
		info.append("版本号 : " + app.getVersionCode() + "\t版本名称 : " + app.getVersionName() + "\tSDK版本 : " + android.os.Build.VERSION.SDK_INT + "\n");
		info.append("开机时间 :" + Utility.getTimes() + "\t当前时间 :" + new Date().toLocaleString() + "\n");
		// info.append("" + Utility.getVersion().toString() + "\n");
		// info.append("" + Utility.getCpuInfo().toString() + "\n");
		// info.append("" + Utility.getOtherInfo(mApp) + "\n");
		saveCrashInfoToFile(info.toString());
	}

	/**
	 * 收集异常信息
	 * 
	 * @param thread
	 * @param ex
	 */
	private void collectCrashExceptionInfo(Thread thread, Throwable ex) {
		StringBuffer exceptionInfo = new StringBuffer();

		exceptionInfo.append("============ 异常信息 ============\n");
		exceptionInfo.append(ex.getMessage() + "\n");
		StackTraceElement[] elements = ex.getStackTrace();

		for (int i = 0; i < elements.length; i++) {
			exceptionInfo.append(elements[i].toString() + "\n");
		}
		saveCrashInfoToFile(exceptionInfo.toString());
	}

	/**
	 * 显示Crash提示,弹出对话框提示用户是否上传异常日志至服务器
	 */
	private void showTipDialog(final Throwable ex) {
		AlertDialog.Builder builder = new AlertDialog.Builder(mApp.getApplicationContext());
		builder.setTitle("异常处理");
		builder.setMessage("您的程序出现异常，是否将异常信息上传至服务器?");
		builder.setPositiveButton("是的", new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				sendCrashReportsToServer();
			}
		});
		builder.setNegativeButton("暂时不", new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		builder.create().show();
	}

	/**
	 * 发送报告到服务器
	 * 
	 * @return
	 */
	private boolean sendCrashReportsToServer() {
		// TODO 开启线程发送报告
		return true;
	}

}
